package com.jonluo.springboot.zookeeper.client;


import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class ZooKeeperClient implements  Watcher {


  private String zkServers = "127.0.0.1:2181";

  private static final int SESSION_TIMEOUT = 5000;

  private static CountDownLatch latch = new CountDownLatch(1);

  private static Logger logger = LoggerFactory.getLogger(ZooKeeperClient.class);

  public ZooKeeperClient(){
    try {
      // 创建 ZooKeeper 客户端
      ZooKeeper zk = new ZooKeeper(zkServers, SESSION_TIMEOUT, this);
      latch.await();
      logger.debug("connected to zookeeper");

      // 创建节点(同步)
      String name = zk.create("/foo", "hello".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
      System.out.println("同步创建节点:"+name);
      // 判断节点是否存在(同步)
      Stat stat = zk.exists("/", null);
      if (stat != null) {
        System.out.println("node exists");
      } else {
        System.out.println("node does not exist");
      }
      // 列出子节点 (同步)
      List<String> children = zk.getChildren("/", null);
      for (String node : children) {
        System.out.println(node);
      }
      // 更新节点数据 (同步)
      stat = zk.setData("/foo", "hi".getBytes(), -1);
      System.out.println(stat != null);
      // 获取节点数据 (同步)
      byte[] data = zk.getData("/foo", null, null);
      System.out.println(new String(data));
      // 删除节点(同步)
      zk.delete("/foo", -1);
      System.out.println("true");


      // 创建节点(异步)
      zk.create("/foo", "hello".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT, new AsyncCallback.StringCallback() {
        @Override
        public void processResult(int rc, String path, Object ctx, String name) {
          System.out.println("异步创建节点："+name);
        }
      }, null);
      Thread.sleep(3000);
      // 判断节点是否存在 (异步)
      zk.exists("/", null, new AsyncCallback.StatCallback() {
        @Override
        public void processResult(int rc, String path, Object ctx, Stat stat) {
          if (stat != null) {
            System.out.println("node exists");
          } else {
            System.out.println("node does not exist");
          }
        }
      }, null);
      Thread.sleep(3000);
      // 列出子节点 (异步)
      zk.getChildren("/", null, new AsyncCallback.ChildrenCallback() {
        @Override
        public void processResult(int rc, String path, Object ctx, List<String> children) {
          for (String node : children) {
            System.out.println(node);
          }
        }
      }, null);
      Thread.sleep(3000);
      // 列出子节点 (异步)
      zk.getChildren("/", null, new AsyncCallback.Children2Callback() {
        @Override
        public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
          for (String node : children) {
            System.out.println(node);
          }
        }
      }, null);
      Thread.sleep(3000);
      // 更新节点数据 (异步)
      zk.setData("/foo", "hi".getBytes(), -1, new AsyncCallback.StatCallback() {
        @Override
        public void processResult(int rc, String path, Object ctx, Stat stat) {
          System.out.println(stat != null);
        }
      }, null);
      Thread.sleep(3000);
      // 获取节点数据 (异步)
      zk.getData("/foo", null, new AsyncCallback.DataCallback() {
        @Override
        public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) {
          System.out.println(new String(data));
        }
      }, null);
      Thread.sleep(3000);
      // 删除节点 (异步)
      zk.delete("/foo", -1, new AsyncCallback.VoidCallback() {
        @Override
        public void processResult(int rc, String path, Object ctx) {
          System.out.println(rc == 0);
        }
      }, null);
      Thread.sleep(3000);









    } catch (Exception e) {
      logger.error("create zookeeper client failure", e);
    }
  }

  @Override
  public void process(WatchedEvent event) {
    if (event.getState() == Event.KeeperState.SyncConnected) {
      latch.countDown();
    }
  }


}
